package view;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;
import java.util.ArrayList;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import model.Order;
import model.Stock;

import server.Server;
import server.exception.InvalidOrderException;
import client.Client;

public class BuyPanel extends JPanel {
	
	private static final long serialVersionUID = 7378979806569332679L;
	
	private Client client;
	private Server server;
	
	private JList stockList;
	private DefaultListModel stockListModel;
	private JPanel stockControls;

	private JLabel available;
	private JTextField buyQuantity;
	private JTextField buyPrice;
	private JButton buy;
	private JLabel selectedStockPrice;
	private JTextArea selling;
	private ArrayList<Stock> stocks;
	
	public BuyPanel() {
		// create GUI components
		stockListModel = new DefaultListModel();
		stockList = new JList(stockListModel);
		stockList.addListSelectionListener(new StockSelectedListener());
		stockControls = new JPanel();
		buyQuantity = new JTextField("0");
		buyPrice = new JTextField("0");
		selectedStockPrice = new JLabel();
		buy = new JButton("Buy Stock");
		buy.addActionListener(new BuyListener());
		selling = new JTextArea();
		available = new JLabel();

		// add them to panel
		setLayout(new BorderLayout());
		add(stockList, BorderLayout.WEST);
		JPanel p = new JPanel(new BorderLayout());
		
		stockControls.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.HORIZONTAL;
		c.insets = new Insets(5, 5, 5, 5);
		c.weightx = 0.5;
		c.gridy = 0;
		
		c.gridy++;
		stockControls.add(new JLabel("Current Price"), c);
		stockControls.add(selectedStockPrice, c);
		
		c.gridy++;
		stockControls.add(new JLabel("You Have"), c);
		stockControls.add(available, c);
		
		c.gridy++;
		stockControls.add(new JLabel("Req. Quantity"), c);
		stockControls.add(buyQuantity, c);

		c.gridy++;
		stockControls.add(new JLabel("At Price"), c);
		stockControls.add(buyPrice, c);

		c.gridy++;
		c.gridx = 1;
		stockControls.add(buy, c);		
		
		p.add(stockControls, BorderLayout.NORTH);
		p.add(new JScrollPane(selling), BorderLayout.CENTER);
		add(p, BorderLayout.CENTER);
	}
	
	/**
	 * Used to update and populate the panels
	 * @param s
	 * 		The Server reference
	 * @param c
	 * 		The client reference
	 * @throws RemoteException
	 */
	public void populate(Server s, Client c) throws RemoteException {
		this.server = s;
		this.client = c;
		stocks = server.getStocks(c);
		stockListModel.clear();
		
		for (Stock stock : stocks) {
			stockListModel.addElement(stock.getName());
		}
		if(!stockListModel.isEmpty()) {
			stockList.setSelectedIndex(0);
		}
	}
	
	/** Listener to handle once stock has been selected **/
	class StockSelectedListener implements ListSelectionListener {
		/**
		 * Updates the panes if a selected item has changed
		 * @param arg
		 * 		The ListSelectionEvent object
		 */
		public void valueChanged(ListSelectionEvent arg) {
			// if the stock item selected has got more the 0
			if (stockList.getSelectedIndex() >= 0) {
				Stock s = stocks.get(stockList.getSelectedIndex());
				try {
					// get the price of the selected item
					selectedStockPrice.setText(String.valueOf(s.getPrice()));
					ArrayList<Order> ol = server.getSellOffers(client, s.getName());
					if (ol != null) {
						selling.setText("");
						for (Order o : ol) {
							selling.append(String.format(
									"Offer of %d at %d (%s)\n", o.getNumber(),
									o.getPrice(), o.getTransactionId()));
						}
					} else {
						selling.setText("nobody is selling this stock");
					}
					
					// get the number of shares the user is currently holding
					int holding = server.getHolding(client, s.getName());
					available.setText(String.valueOf(holding));
				} catch (RemoteException e) {
					JOptionPane.showMessageDialog(BuyPanel.this,
							"An error occured while communicating with server: "
									+ e.getMessage(), "Error",
							JOptionPane.ERROR_MESSAGE);
				}
			}
		}
	}
	
	/** Listener to handle buy; once it has been selected**/
	class BuyListener implements ActionListener {
		
		public void actionPerformed(ActionEvent arg0) {
			try {
				// user requested to buy a item
				server.buyStock(client, (String)stockList.getSelectedValue(),
						Integer.parseInt(buyQuantity.getText()),
						Integer.parseInt(buyPrice.getText()));
			} catch (NumberFormatException e) {
				JOptionPane.showMessageDialog(BuyPanel.this,
						"Please enter a numerical value.", "Error",
						JOptionPane.ERROR_MESSAGE);
			} catch (RemoteException e) {
				JOptionPane.showMessageDialog(BuyPanel.this,
						"An error occured while communicating with server: " + e.getMessage(),
						"Error", JOptionPane.ERROR_MESSAGE);
			} catch (InvalidOrderException e) {
				JOptionPane.showMessageDialog(BuyPanel.this, e.getMessage(),
						"Error", JOptionPane.ERROR_MESSAGE);
			}
			catch (NullPointerException e) {
				JOptionPane.showMessageDialog(BuyPanel.this, "Please fill out the required fields",
						"Error", JOptionPane.ERROR_MESSAGE);
			}
		}

	}
	
	/**
	 * Get the button of buy
	 * @return buy
	 * 		The JButton associated with buy
	 */
	public JButton getBuyButton() {
		return buy;
	}

}
